"""
====================================================================
数据库Schema定义 / Database Schemas Definition
====================================================================
功能说明：
定义MongoDB集合的结构、字段说明和索引需求。
为新的灵活查询系统提供统一的数据结构规范。

作者: Data Analysis Team
日期: 2025-11-06
====================================================================
"""

from typing import List, Dict, Optional
from datetime import datetime, timedelta
from pydantic import BaseModel, Field


# ====================================================================
# 1. 设备评分明细表 (equipment_scores_detail)
# ====================================================================

class StatsModel(BaseModel):
    """统计指标"""
    规则标准类型: Optional[str] = None
    达标天数: Optional[int] = None
    达标时长: Optional[float] = None
    实际统计天数: Optional[int] = None
    正常天数: Optional[int] = None
    总工作时间: Optional[float] = None
    未进场天数: Optional[int] = None
    维修停机天数: Optional[int] = None
    维修天数: Optional[int] = None
    出勤日运行时间均值: Optional[float] = None
    所有运行时间均值: Optional[float] = None
    运行时间标准差: Optional[float] = None
    一致性: Optional[float] = None
    出勤天数: Optional[float] = None
    达标率: Optional[float] = None
    可工作天数: Optional[float] = None
    可工作率: Optional[float] = None
    总时长达标率: Optional[float] = None


class ScoresModel(BaseModel):
    """6维评分"""
    A_可用性: float = Field(..., description="可用性（0-100）")
    C_出勤覆盖: float = Field(..., description="出勤覆盖（0-100）")
    U_强度利用: float = Field(..., description="强度利用（0-100）")
    S_一致性: float = Field(..., description="一致性（0-100）")
    P_合规达标: float = Field(..., description="合规达标（0-100）")
    R_可靠性: float = Field(..., description="可靠性（0-100）")
    综合分: float = Field(..., description="综合分（0-100）")


class EquipmentScoreDetail(BaseModel):
    """设备评分明细表"""
    memberId: int = Field(..., description="公司ID")
    imei: str = Field(..., description="设备IMEI")
    region_name: Optional[str] = None
    region_id: Optional[int] = None
    project_name: Optional[str] = None
    project_id: Optional[int] = None
    equipment_type: Optional[str] = None

    # 时间维度
    period_type: str = Field(default="monthly", description="monthly | weekly | daily")
    period_start: datetime = Field(..., description="统计周期开始")
    period_end: datetime = Field(..., description="统计周期结束")
    year: int = Field(..., description="年份")
    month: int = Field(..., description="月份（1-12）")
    week: Optional[int] = None  # week | 周数（1-53）

    # 统计指标和评分
    stats: Optional[StatsModel] = None
    scores: ScoresModel = Field(..., description="6维评分")

    # 元数据
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)
    version: int = Field(default=1, description="版本号，用于并发控制")

    class Config:
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }

    @staticmethod
    def get_indices():
        """返回该集合需要的索引列表"""
        return [
            # 基础查询索引
            [("memberId", 1), ("period_start", 1), ("period_end", 1)],
            [("memberId", 1), ("imei", 1), ("period_start", 1)],
            [("memberId", 1), ("project_name", 1), ("period_start", 1)],
            [("memberId", 1), ("region_name", 1), ("period_start", 1)],

            # 排序索引（用于Top/Bottom N查询）
            [("memberId", 1), ("scores.综合分", -1), ("period_start", 1)],
            [("memberId", 1), ("scores.A_可用性", -1), ("period_start", 1)],
            [("memberId", 1), ("scores.C_出勤覆盖", -1), ("period_start", 1)],

            # 时间范围查询
            [("period_start", 1), ("period_end", 1)],
        ]


# ====================================================================
# 2. 项目/区域聚合表 (equipment_scores_aggregated)
# ====================================================================

class AverageScoresModel(BaseModel):
    """平均评分"""
    A_可用性: float
    C_出勤覆盖: float
    U_强度利用: float
    S_一致性: float
    P_合规达标: float
    R_可靠性: float
    综合分: float


class EquipmentScoresAggregated(BaseModel):
    """项目/区域聚合表"""
    memberId: int = Field(..., description="公司ID")
    aggregation_level: str = Field(..., description="region | project | company")
    dimension_id: str = Field(..., description="区域ID或项目ID或ALL")
    dimension_name: str = Field(..., description="区域名或项目名")

    period_type: str = Field(default="monthly", description="monthly | weekly")
    period_start: datetime = Field(..., description="统计周期开始")
    period_end: datetime = Field(..., description="统计周期结束")
    year: int = Field(..., description="年份")
    month: int = Field(..., description="月份（1-12）")

    # 聚合数据
    equipment_count: int = Field(..., description="设备数量")
    avg_scores: AverageScoresModel = Field(..., description="平均评分")

    # 源数据统计（便于二次分析）
    total_work_hours: Optional[float] = None
    total_comply_days: Optional[int] = None

    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    class Config:
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }

    @staticmethod
    def get_indices():
        """返回该集合需要的索引列表"""
        return [
            # 主查询索引
            [("memberId", 1), ("aggregation_level", 1), ("dimension_id", 1), ("period_start", 1)],

            # 排序索引
            [("memberId", 1), ("aggregation_level", 1), ("avg_scores.综合分", -1), ("period_start", 1)],

            # 时间查询
            [("period_start", 1), ("period_end", 1)],
        ]


# ====================================================================
# 3. 周度统计表 (equipment_weekly_stats)
# ====================================================================

class WeeklyStatsData(BaseModel):
    """周度统计数据"""
    met_days: int = Field(..., description="达标天数")
    counted_days: int = Field(..., description="统计总天数")
    frequency: int = Field(..., description="周目标频次")
    is_week_met: int = Field(..., description="是否达标：0或1")


class EquipmentWeeklyStats(BaseModel):
    """周度统计表"""
    memberId: int = Field(..., description="公司ID")
    imei: str = Field(..., description="设备IMEI")
    region_name: Optional[str] = None
    project_name: Optional[str] = None

    week_period: str = Field(..., description="周期标识，格式：2025-W01")
    week_start: datetime = Field(..., description="周开始日期")
    week_end: datetime = Field(..., description="周结束日期")
    year: int = Field(..., description="年份")
    week: int = Field(..., description="周数（1-53）")

    stats: WeeklyStatsData = Field(..., description="周度统计数据")

    created_at: datetime = Field(default_factory=datetime.utcnow)

    class Config:
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }

    @staticmethod
    def get_indices():
        """返回该集合需要的索引列表"""
        return [
            # 基础查询索引
            [("memberId", 1), ("imei", 1), ("week_start", 1)],
            [("memberId", 1), ("project_name", 1), ("week_start", 1)],
            [("memberId", 1), ("region_name", 1), ("week_start", 1)],

            # 时间查询
            [("week_start", 1), ("week_end", 1)],
        ]


# ====================================================================
# 4. AI分析报告表 (analysis_reports)
# ====================================================================

class AnalysisScope(BaseModel):
    """分析范围"""
    level: str = Field(..., description="company | region | project | equipment")
    region_ids: Optional[List[str]] = None
    project_ids: Optional[List[str]] = None
    imeis: Optional[List[str]] = None


class ReportSummary(BaseModel):
    """报告摘要（用于列表展示）"""
    total_equipment: int = Field(..., description="设备总数")
    avg_score: float = Field(..., description="平均综合分")
    high_risk_count: int = Field(..., description="高风险设备数")
    problem_count: Optional[int] = None  # 识别的问题数


class AnalysisReport(BaseModel):
    """AI分析报告表"""
    memberId: int = Field(..., description="公司ID")
    report_type: str = Field(..., description="equipment_analysis | health_analysis")

    # 分析时间范围
    period_start: datetime = Field(..., description="统计周期开始")
    period_end: datetime = Field(..., description="统计周期结束")

    # 分析范围
    scope: AnalysisScope = Field(..., description="分析范围")

    # AI生成的报告
    ai_result: str = Field(..., description="AI分析报告内容（Markdown格式）")
    model: str = Field(..., description="使用的AI模型")

    # 报告摘要
    summary: ReportSummary = Field(..., description="报告摘要")

    # 元数据
    created_at: datetime = Field(default_factory=datetime.utcnow)
    ttl: datetime = Field(
        default_factory=lambda: datetime.utcnow() + timedelta(days=90),
        description="过期时间（TTL索引将在此后自动删除）"
    )

    class Config:
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }

    @staticmethod
    def get_indices():
        """返回该集合需要的索引列表"""
        return [
            # 主查询索引
            [("memberId", 1), ("period_start", 1)],
            [("memberId", 1), ("report_type", 1), ("created_at", -1)],

            # TTL索引（自动清理过期文档）
            [("ttl", 1), {"expireAfterSeconds": 0}],
        ]


# ====================================================================
# 5. 向后兼容：旧的equipment_analysis结构（用于迁移期间）
# ====================================================================

class EquipmentAnalysisLegacy(BaseModel):
    """旧格式的equipment_analysis（保留用于迁移）"""
    memberId: int
    time_range: Dict
    type: str
    summary: Optional[List[Dict]] = None
    monthly_scores: Optional[List[Dict]] = None
    weekly_summary: Optional[List[Dict]] = None
    region_scores: Optional[List[Dict]] = None
    project_scores: Optional[List[Dict]] = None
    score_sort: Optional[Dict] = None
    overall_score: Optional[Dict] = None
    ai_result: Optional[str] = None
    created_at: datetime = Field(default_factory=datetime.utcnow)


# ====================================================================
# 6. 集合初始化脚本
# ====================================================================

COLLECTIONS_CONFIG = {
    "equipment_scores_detail": {
        "name": "equipment_scores_detail",
        "description": "设备评分明细表（最细粒度）",
        "indices": EquipmentScoreDetail.get_indices(),
    },
    "equipment_scores_aggregated": {
        "name": "equipment_scores_aggregated",
        "description": "项目/区域聚合表（可选，用于优化高频查询）",
        "indices": EquipmentScoresAggregated.get_indices(),
    },
    "equipment_weekly_stats": {
        "name": "equipment_weekly_stats",
        "description": "周度统计表（独立存储周度数据）",
        "indices": EquipmentWeeklyStats.get_indices(),
    },
    "analysis_reports": {
        "name": "analysis_reports",
        "description": "AI分析报告表（90天自动清理）",
        "indices": AnalysisReport.get_indices(),
    },
    "equipment_analysis": {
        "name": "equipment_analysis",
        "description": "旧的equipment_analysis集合（迁移期间保留）",
        "indices": [],
    },
}


def print_schema_info():
    """打印Schema信息（用于调试）"""
    print("\n" + "="*70)
    print("数据库Schema配置信息")
    print("="*70)

    for coll_name, config in COLLECTIONS_CONFIG.items():
        print(f"\n集合名: {coll_name}")
        print(f"描述: {config['description']}")
        if config['indices']:
            print(f"索引数量: {len(config['indices'])}")
            for i, idx in enumerate(config['indices'], 1):
                print(f"  [{i}] {idx}")
        else:
            print("  无自定义索引")

    print("\n" + "="*70 + "\n")


if __name__ == "__main__":
    print_schema_info()
